Тернарный оператор и оператор запятая
Название «тернарный» произошло от латинского ternarius – тройной. Оператор принимает три аргумента. Если первый аргумент истина, то возвращается второй аргумент, если ложь, то возвращается третий.
Синтаксис оператора
<условие> ? <аргумент 2> : <аргумент 3>
Например, пользователь вводит два числа. Присвоить переменной значение наименьшего.
#define _CRT_SECURE_NO_WARNINGS
#include <conio.h>
#include <stdio.h>
void main() {
int a, b, c;
scanf("%d %d", &a, &b);
c = (a > b) ? b : a;
printf("%d", c);
_getch();
}
Другой пример: вывести модуль числа
#define _CRT_SECURE_NO_WARNINGS
#include <conio.h>
#include <stdio.h>
void main() {
int a;
scanf("%d", &a);
printf("%d", a > 0 ? a : -a);
_getch();
}
Здесь тернарный оператор используется вместо аргумента функции printf
.
Оператор ?
может быть вложенным. Например, найдём среднее из трёх чисел:
#include <conio.h>
#include <stdio.h>
void main() {
int a = 1;
int b = 2;
int c = 3;
int mid;
mid = (a > b) ? (a > c) ? (c > b) ? c : b : a : (b > c) ? (c > a) ? c : a : b;
printf("%d", mid);
_getch();
}
Видно, что в этом примере тернарный оператор становится нечитаемым. Поэтому не используйте вложенные тернарные операторы и заменяйте их на обычные ветвления
#include <conio.h>
#include <stdio.h>
void main() {
int a = 1;
int b = 2;
int c = 3;
int mid;
if (a > b) {
if (a > c) {
if (c > b) {
mid = c;
} else {
mid = b;
}
} else {
mid = a;
}
} else {
if (b > c) {
if (c > a) {
mid = c;
} else {
mid = a;
}
} else {
mid = b;
}
}
printf("%d", mid);
_getch();
}
Для тернарного оператора определён порядок выполнения. Все значение и побочные эфекты, связанные с первым выражением реализуются перед тем, как будут реализованы значения и побочные эффекты для второго и третьего выражений.
#include <conio.h>
#include <stdio.h>
void main() {
int x = 0;
//Выведет 200, так как ++ постфиксный
printf("%d\n", x++ ? 100: 200);
//Выведет 1, так как после проверки x был увеличен
printf("%d\n", x);
x = 0;
//Выведет 100, так как сначала будет увеличен x
printf("%d\n", ++x ? 100 : 200);
printf("%d\n", x);
x = 0;
printf("%d\n", ++x ? x++ : x++);
//Выведет 2, так как будет выполнено первое условие
//и x будет инкрементирован повторно
printf("%d\n", x);
_getch();
}
Оператор запятая.
Оператор ,
принимает два аргумента, выполняет первый, после этого выполняет второй и возвращает его значение. Например:
#include <conio.h>
#include <stdio.h>
void main() {
int a, b, c;
c = (a = 3, b = 4);
printf("%d", c);
_getch();
}
В данном примере c будет равно 4. Выражение
(a = 3, b = 4)
вернёт 4. Очевидно, что если убрать скобки, то c станет равным 3, так как запятая в этом случае будет разделять c = a = 3
и b = 4
, с
присвоится значение 3, а 4 будет возвращено оператором запятая, но потеряется. То есть выражение
c = a = 3, b = 4;
эквивалентно
(c = a = 3), (b = 4);
Если написать
c = (a = 3, b = 4, d = 5);
то будет возвращено значение 5.
В выражении
#include <conio.h>
#include <stdio.h>
void main() {
int c;
c = 1, 2, 3, 4, 5;
printf("%d", c);
_getch();
}
с будет равно 1, так как этот код эквивалентен такому
((((c = 1), 2), 3), 4), 5;
Такое поведение оператора запятая часто приводит к следующей ошибке. Вместо десятичной точки
a = 0.5;
пишут
a = 0,5;
Таким образом, переменная a будет иметь значение 0.
Для оператора ,
гарантированно выполнение по порядку, слева направо. Оператор запятая поэтому используется в условиях, когда нужно выполнить несколько действий или получить значение. Например
#include <conio.h>
#include <stdio.h>
int foo(int a) {
return a % 5 + a*a;
}
void main() {
int i = 0;
int mod;
while (mod = foo(i), mod < 100) {
printf("%d ", i);
i++;
}
_getch();
}
Часто запятая используется в цикле for
, так как позволяет задавать несколько значений или выполнять несколько операций за раз. Пример – переворачивание массива.
#include <conio.h>
#include <stdio.h>
#define SIZE 10
void main() {
int arr[SIZE] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int i, j, tmp;
for (i = 0, j = SIZE - 1; i < SIZE / 2; i++, j--) {
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
for (i = 0; i < SIZE; i++) {
printf("%d ", arr[i]);
}
_getch();
}